{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 1 引言\n",
    "感知机是一种简单且易于实现的二分类判别模型，主要思想是通过误分类驱动的损失函数结合梯度下降发求解一个超平面将线性可分的数据集划分为两个不同的类别（+1类和-1类）。  \n",
    "在神经网络、支持向量机等算法盛行的当下，感知机模型应用得并不多，但必须承认，感知机却是神经网络和支持向量机的基础，所以还是很有必要学习一下的，本文接下来的内容将从感知机数学描述、损失函数、两种不同学习形式等方面详细介绍感知机，最后使用Python实现感知机两种学习形式。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 2 感知机模型及损失函数\n",
    "## 2.1 数学描述\n",
    "对于给定训练样本数据集$D = \\{ ({x_i},{y_i})\\} _{i = 1}^m$,${x_i} \\in X \\subseteq {R^n}$表示训练样本的特征向量,${y_i} \\in Y = \\{  + 1, - 1\\} $表示样本类别。$x$与$y$之间的如下函数关系：\n",
    "$$y = f(x) = sign(w \\cdot x + b)$$\n",
    "称为感知机。其中，$w \\in {R^n}$称为感知机的权值系数或者权值向量，$b \\in R$称为偏置，$sign$是符号函数，有：\n",
    "$$sign = \\left\\{ {_{ - 1,    x < 0}^{ + 1,    x \\geqslant 0}} \\right.$$\n",
    "从定义上可以看出，感知机最终目标就是求解出$w$和$b$。我们可以从几何上对感知机进行理解，如果以$w$为法向量，以$b$为截距，可以确定一超平面：\n",
    "$$w \\cdot x + b = 0$$\n",
    "通过这一超平面，可以顺利将对数据集进行划分。以二维数据为例，如下图所示,当样本点$x$刚好落在超平面上时，有$w \\cdot x + b = 0$，当$x$落在超平面下方时，有$w \\cdot x + b < 0$，通过$sign$函数后输出为$-1$,也就是标记为$-1$类；当$x$落在超平面上方时，有$w \\cdot x + b > 0$，通过$sign$函数后输出为$+1$,也就是标记为$+1$类。注意，这样的超平面一般不唯一，也就是说感知机最终解可以有很多个，受参数初始值、训练样本输入顺序等因素的影响，每次训练时所获得的超平面都可能不一样。\n",
    "![image]()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.2 损失函数\n",
    "为了求解参数$w$和$b$，确定最终的分割超平面，我们需要定义一个目标函数或者说损失函数，通过最小化损失函数来达到目的。在感知机模型中，以误分类的样本对象与分割超平面间的距离之和最为损失函数。我们高中时学过，对于点$({x_0},{y_0})$，到平面$A \\cdot x + B \\cdot y + C = 0$的距离为：\n",
    "$$dist = \\frac{{|A \\cdot {x_0} + B \\cdot {y_0} + C|}}{{\\sqrt {{A^2} + {B^2}} }} $$\n",
    "将这一公式扩展到超平面中，对于超平面$w \\cdot x + b = 0$，误分类点$x_i$到超平面的距离为：\n",
    "$$dist = \\frac{{|w \\cdot xi + b|}}{{\\left\\| w \\right\\|}} $$\n",
    "式中，${\\left\\| w \\right\\|}$是$w$的$L_2$范数，等同于上面的${\\sqrt {{A^2} + {B^2}} }$。\n",
    "为了方便计算，我们需要将分子中的绝对值去掉，怎么去掉呢？因为$({x_i},{y_i})$是误分类样本点，$y_i$与${w \\cdot xi + b}$一定是异号的，所以：\n",
    "$$ - {y_i} \\cdot (w \\cdot x_i + b) > 0 $$\n",
    "且因为$|{y_i}| = 1$，所以：\n",
    "$$ - {y_i} \\cdot (w \\cdot x_i + b) = |w \\cdot x_i + b| $$\n",
    "于是，$({x_i},{y_i})$到超平面的距离可以表示为：\n",
    "$$\\frac{{ - {y_i} \\cdot (w \\cdot x_i + b)}}{{\\left\\| w \\right\\|}} $$\n",
    "假设$M$是所有误分类点组成的集合，那么所有误分类点到超平面距离总和为：\n",
    "$$\\sum\\limits_{{x_i} \\in M} {\\frac{{ - {y_i} \\cdot (w \\cdot {x_i} + b)}}{{\\left\\| w \\right\\|}}}  \\tag{1}$$\n",
    "这就是我们需要的损失函数的雏形了，之所以说是雏形，是因为我们还可以通过令$\\left\\| w \\right\\|{\\text{ = }}1$对上式进一步化简，于是有：\n",
    "$$L(w,b) = \\sum\\limits_{{x_i} \\in M} { - {y_i} \\cdot (w \\cdot {x_i} + b)} \\tag{2}$$\n",
    "$L(w,b)$就是我们最终需要的损失函数。\n",
    "为什么可以直接令$\\left\\| w \\right\\|{\\text{ = }}1$来化简式（1）呢？\n",
    "\n",
    "我们可以在权值向量$w$中添加一个$w_0$元素，在特征向量$x_i$中添加一个第0纬度${x^{(0)}} = 1$，令偏置$b = {w_0} \\cdot {x^{(0)}}$，这样，我们就把偏置$b$也放进了权值向量$w$中，那式（1）就变为：\n",
    "$$\\sum\\limits_{{x_i} \\in M} {\\frac{{ - {y_i} \\cdot w \\cdot {x_i}}}{{\\left\\| w \\right\\|}}} $$\n",
    "此时，分子和分母都含有$w$,当分子的$w$扩大$N$倍时，分母的$L_2$范数也会扩大N倍。也就是说，分子和分母有固定的倍数关系。那么我们可以固定分子或者分母为1，然后求分母的倒数或者分子自己的最小化作为损失函数，这样可以简化我们的损失函数。在感知机模型中，采用的是保留分子的策略。  \n",
    "另一种解释，当把偏置$b$包含进$w$后，超平面表达式也简化成$w \\cdot {x_i} = 0$，无论是把$w$扩大多少倍、缩小多少倍，都对超平面没有影响（就像$x + y - 1 = 0$与$2x + 2y - 2 = 0$始终表示同一条直线），那么我们总能找到一个倍数，将$w$缩小到满足${\\left\\| w \\right\\|}=1$，但并不影响我们获得最终的超平面，但是令${\\left\\| w \\right\\|}=1$后却有助于我们化简和求解。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 3 优化方法\n",
    "上一节中，我们介绍了感知机模型损失函数$L(w,b)$的由来，接下来就要说说怎么通过优化损失函数来获得最终的超平面。在感知机模型中，有两种优化方式：原始形式和对偶形式。\n",
    "## 3.1 原始形式\n",
    "原始形式采用的是梯度下降法进行求解，如果对梯度下降法不了解，可以参看前面写过的一篇[博客](https://www.cnblogs.com/chenhuabin/p/11166726.html)。这里需要注意的是，在上一小节中说过，感知机是基于误分类驱动的一种模型，所以不能使用整个数据集进行梯度下降优化，只能对误分类样本集合$M$采用随机梯度下降法或者小批量梯度下降法进行优化。\n",
    "对损失函数$L(w,b)$求偏导：\n",
    "$$\\frac{{\\partial L(w,b)}}{{\\partial w}} =  - \\sum\\limits_{{x_i} \\in M} {{y_i} \\cdot {x_i}} $$\n",
    "$$\\frac{{\\partial L(w,b)}}{{\\partial b}} =  - \\sum\\limits_{{x_i} \\in M} {{y_i}} $$\n",
    "那么，$w$的梯度下降迭代公式为：\n",
    "$$w = w + \\alpha  \\cdot \\sum\\limits_{{x_i} \\in M} {{y_i} \\cdot {x_i}} $$\n",
    "偏置$b$的梯度下降迭代公式为：\n",
    "$$b = b + \\alpha  \\cdot \\sum\\limits_{{x_i} \\in M} {{y_i}} $$\n",
    "式中，$\\alpha $是学习率。\n",
    "感知机模型中，一般采用随机梯度下降法进行优化，每次使用一个误分类样本点进行梯度更新。假设$(x_i,y_i)$是$M$中的一个误分类点，进行梯度更新：\n",
    "$$w = w + \\alpha  \\cdot {y_i}{x_i} \\tag{3}$$\n",
    "$$b = b + \\alpha  \\cdot {y_i} \\tag{4}$$\n",
    "总结一下原始形式优化步骤。\n",
    "输入：训练样本数据集$D = \\{ ({x_i},{y_i})\\} _{i = 1}^m$,${x_i} \\in X \\subseteq {R^n}$,${y_i} \\in Y = \\{  + 1, - 1\\} $，学习率% $\\alpha  \\in (0,1)$  \n",
    "输出：$w$,$b$；感知机模型$f(x) = sign(w \\cdot x + b) $  \n",
    "（1）初始化$w_0$，$b_0$；  \n",
    "（2）在$D$中选取任意点$(x_i,y_i)$；  \n",
    "（3）通过${y_i} \\cdot (w \\cdot {x_i} + b)$的值判断是否是误分类点，如果是，使用式（3）、（4）更新参数；  \n",
    "（4）回到步骤（2）直到准确率满足条件。\n",
    "## 3.2 对偶形式\n",
    "对偶形式时原始形式在执行效率上的优化。通过3.1小节中，我们知道，每当一个样本点$x_i$被错误分类一次时，都会使用式（3）（4）更新一次参数，那么，如果样本点$x_i$在迭代过程中被错误分类多次（假设$n_i$次），那么就回有$n_i$次参与到参数更新中，我们假设参数$w$和$b$的初始值都为0向量，那么，最终获得的参数$w$和$b$为：\n",
    "$$w = \\sum\\limits_{i = 1}^N {{\\beta _i} {y_i}{x_i}}  \\tag{5}$$\n",
    "$$b = \\sum\\limits_{i = 1}^N {{\\beta _i} {y_i}}  \\tag{6}$$\n",
    "这是在对偶形式中的参数更新方式，式中，${\\beta _i} ={n_i}\\alpha$。另外，在原始形式中，我们使用${y_i}(w \\cdot {x_i} + b) \\leqslant 0$来判断样本点$x_i$是否被错误分类，将式（5）（6）代入这一判别式中，得：\n",
    "$${y_i}(\\sum\\limits_{i = 1}^N {{\\beta _i} {y_i}{x_i}}  \\cdot {x_j} + \\sum\\limits_{i = 1}^N {{\\beta _i} {y_i}}) \\leqslant 0 \\tag{7}$$\n",
    "在对偶形式中，采用式（7）判断样本点是否正确分类，观察后可以发现，式（7）中有两个样本点$x_i$和$x_j$内积计算，这个内积计算的结果在下面的迭代过程中需要多次被重复使用，如果我们事先用矩阵运算计算出所有的样本之间的内积，那么在算法迭代过程中， 仅仅一次的矩阵内积运算比原始形式中每遍历一个样本点都要计算$w$与$x_i$的内积要省时得多，这也是对偶形式的感知机模型比原始形式优的原因。  \n",
    "在感知机模型中，样本的内积矩阵称为Gram矩阵，它是一个对称矩阵，记为$G = {[{x_i},{x_j}]_{m \\times m}}$。\n",
    "总结一下对偶形式的步骤。  \n",
    "输入：训练样本数据集$D = \\{ ({x_i},{y_i})\\} _{i = 1}^m$,${x_i} \\in X \\subseteq {R^n}$,${y_i} \\in Y = \\{  + 1, - 1\\} $，学习率% $\\alpha  \\in (0,1)$  \n",
    "输出：$w$,$b$；感知机模型$f(x) = sign(w \\cdot x + b) $  \n",
    "（1）初始化所有$n_i$值为0；  \n",
    "（2）计算Gram矩阵；  \n",
    "（3）在$D$中选取任意点$(x_i,y_i)$；  \n",
    "（4）如果${y_i}(\\sum\\limits_{i = 1}^N {{\\beta _i} {y_i}{x_i}}  \\cdot {x_j} + \\sum\\limits_{i = 1}^N {{\\beta _i} {y_i}}) \\leqslant 0 $，令${\\beta _i} = {\\beta _i} + \\alpha $；  \n",
    "（5）检查是否还有误分类样本点，如果有，回到步骤（2）；如果没有，（5）（6）计算$w$、$b$最终值。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 4 算法实现"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt \n",
    "import copy"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 先来制造一批数据\n",
    "a = np.random.normal(20,5,300)\n",
    "b = np.random.normal(15,5,300)\n",
    "cluster1 = np.array([[x, y, -1] for x, y in zip(a,b)])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = np.random.normal(45,5,300)\n",
    "b = np.random.normal(40,5,300)\n",
    "cluster2 = np.array([[x, y, 1] for x, y in zip(a,b)])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "dataset = np.append(cluster1,cluster2, axis=0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 95,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "for i in dataset:\n",
    "    plt.scatter(i[0], i[1],c='black',s=6)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 93,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "600"
      ]
     },
     "execution_count": 93,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(dataset)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 175,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Perception(object):\n",
    "\n",
    "    def __init__(self):\n",
    "        \"\"\"\n",
    "        感知机模型\n",
    "        \"\"\"\n",
    "        self.w = 0\n",
    "        self.b = 0\n",
    "    \n",
    "    def fit_raw_mod(self, train_data, lr=1, max_epoch=None, min_error_rate=0):\n",
    "        \"\"\"\n",
    "        原始模式的感知机训练方法，当达到最大迭代次数或错误率降到最小范围退出\n",
    "        train_data：训练数据集\n",
    "        lr：学习率\n",
    "        max_epoch：最大迭代次数\n",
    "        min_error_rate：最小错误率\n",
    "        \"\"\"\n",
    "        self.w = np.zeros(train_data.shape[1]-1)  # 根据训练集维度初始化权重系数\n",
    "        epoch = 1  # 记录迭代次数\n",
    "        while True:\n",
    "            error_count = 0  # 记录错误分类样本数\n",
    "            for sample in train_data:\n",
    "                xi = sample[0:-1]\n",
    "                yi = sample[-1]\n",
    "                distance = yi * (self.w @ xi + self.b)  # yi*(w⋅xi*+b)\n",
    "                if distance <= 0: # 对于判断错误的样本点\n",
    "                    self.w += lr * sample[-1] * sample[0:-1]\n",
    "                    self.b += lr * sample[-1]\n",
    "                    error_count += 1\n",
    "            # 每完成一次迭代之后，验证一次准确率，准确率达标则退出\n",
    "            current_error_rate = float(error_count) / train_data.shape[0]\n",
    "            # print('epoch {0}，current_error_rate: {1}'.format(epoch+1, current_error_rate))\n",
    "            # print('w:{0}, b:{1}'.format(self.w, self.b))\n",
    "            # self.show_graph(train_data)  # 每一次迭代都展示一次图像\n",
    "            if current_error_rate <= min_error_rate:\n",
    "                break\n",
    "            if isinstance(max_epoch, int) and epoch >= maxepoch:\n",
    "                break\n",
    "            epoch += 1\n",
    "        print('w:{0}, b:{1}'.format(self.w, self.b))\n",
    "        self.show_graph(train_data)\n",
    "        \n",
    "    def fit_dual_mod(self,train_data,lr=1):\n",
    "        \"\"\"\n",
    "        对偶模式的感知机训练方法\n",
    "        train_data：训练数据集\n",
    "        lr：学习率\n",
    "        \"\"\"\n",
    "        x_train = train_data[:,:-1]\n",
    "        y_train = train_data[:,-1]\n",
    "        num_samples, num_features = x_train.shape\n",
    "        beta = np.zeros((num_samples,))\n",
    "        self.b = 0\n",
    "\n",
    "        # 计算 Gram 矩阵\n",
    "        gram = np.dot(x_train, x_train.T)\n",
    "\n",
    "        while True:\n",
    "            error_count = 0\n",
    "            for i in range(num_samples):\n",
    "                inner_product = gram[i]\n",
    "                y_i = y_train[i]\n",
    "                \n",
    "                distance = y_i * (np.sum(beta * y_train * inner_product) + self.b)\n",
    "                # 对于误分类点，修正 beta 和 偏置b，跳出本层循环，重新遍历数据计算，开始新的循环\n",
    "                if distance <= 0:\n",
    "                    error_count += 1\n",
    "                    beta[i] = beta[i] + lr\n",
    "                    self.b = self.b + lr * y_i\n",
    "                    break  \n",
    "            # 数据没有误分类点，跳出 while 循环\n",
    "            if error_count == 0:\n",
    "                break\n",
    "        self.w = np.sum(beta * y_train * x_train.T, axis=1)  # 计算w参数最终值\n",
    "        print('w:{0}, b:{1}'.format(self.w, self.b))\n",
    "        self.show_graph(train_data)  # 展示图像\n",
    "\n",
    "        \n",
    "    def predict(self, sample):\n",
    "        \"\"\"\n",
    "        输入一个样本点，判断是-1类还是+1类\n",
    "        sample：样本点\n",
    "        \"\"\"\n",
    "        output = self.w @ sample + self.b\n",
    "        return 1 if output >= 0 else -1\n",
    "    \n",
    "    def show_graph(self, train_data):\n",
    "        \"\"\"\n",
    "        把训练出来的超平面图像展示出来\n",
    "        \n",
    "        \"\"\"\n",
    "        for sample in train_data:\n",
    "            if sample[-1] == 1:\n",
    "                plt.scatter(sample[0], sample[1],c='black',s=6)\n",
    "            else:\n",
    "                plt.scatter(sample[0], sample[1],c='red',s=6)\n",
    "        x = np.linspace(0.,60.,200)\n",
    "        y = -(self.w[0]*x + self.b) / self.w[1]\n",
    "        plt.plot(x,y)\n",
    "        plt.show()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 176,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "w:[8.54367705 9.34962314], b:-542.0\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "model = Perception()\n",
    "model.fit_raw_mod(dataset, lr=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 177,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "w:[ 6.06428531 19.42194872], b:-749.0\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "model = Perception()\n",
    "model.fit_dual_mod(dataset, lr=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 178,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "-1"
      ]
     },
     "execution_count": 178,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model.predict(np.array([20,30]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 179,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 179,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model.predict(np.array([50,50]))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "study_python",
   "language": "python",
   "name": "study_python"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
